import api from '@/libs/request'
import { type GeometryOptionalCoordinates, useLocationStore } from '@/store/modules/location'
import { type Geometry, GeometryType } from '@/apis/address/type'
import { type AmapKeys, useAmapKeyStore } from '@/store/modules/amapKey'
import { type R } from '@/utils/types'

/**
 * 接口获取 高德 的各项 key
 */
export const doGetAmapKey = () => {
  return new Promise<R<AmapKeys>>((resolve, reject) => {
    api
      .post<AmapKeys>('gruul-mall-carrier-pigeon/geo/conf')
      .then((res) => {
        if (res.code === 200 && res.data) {
          resolve(res)
        } else {
          reject({ res, msg: '服务器获取高德key失败,请前往后台配置' })
        }
      })
      .catch((error) => {
        reject(error)
      })
  })
}

/**
 * 逆地址解析 可选择存储 store
 * @param {Array} location location[0]:经度,[-180,180],负数表示西经。 location[1]:纬度,[-90,90],负数表示南纬
 * 文档地址: https://lbs.amap.com/api/webservice/guide/api/georegeo
 */
export const locToAddress = (location: [number, number], saveStore = true) => {
  return new Promise<GeometryOptionalCoordinates>((resolve, reject) => {
    uni.request({
      // 逆地理编码 需要web服务高德key
      url: `https://restapi.amap.com/v3/geocode/regeo?key=${useAmapKeyStore().getAmapWebServiceKey}&location=${location[0]},${location[1]}`,
      success: (res: any) => {
        const result = res.data
        if (result.status === '1' && result.infocode === '10000') {
          let tempObj = result.regeocode
          const area = [] as unknown as [string, string, string?]
          if (tempObj.addressComponent.province.length) {
            area.push(tempObj.addressComponent.province)
          }
          if (tempObj.addressComponent.city.length) {
            area.push(tempObj.addressComponent.city)
          }
          if (tempObj.addressComponent.district.length) {
            area.push(tempObj.addressComponent.district)
          }
          if (area.length < 2) {
            area.push('')
          }
          const resp = {
            location: {
              type: GeometryType.Point,
              coordinates: location,
            },
            address: tempObj.formatted_address
              .replace(tempObj.addressComponent.province, '')
              .replace(tempObj.addressComponent.city, '')
              .replace(tempObj.addressComponent.district, ''),
            area,
          } as GeometryOptionalCoordinates
          if (saveStore) {
            useLocationStore().SET_ALL(resp)
          }
          resolve(resp)
        } else {
          if (saveStore) {
            useLocationStore().SET_ADDRESS('获取地址失败，点击手动设置地址')
          }
          reject(res)
        }
      },
      fail: (err) => {
        console.log('获取位置信息失败', err)
        if (saveStore) {
          useLocationStore().SET_ADDRESS('获取地址失败，点击手动设置地址')
        }
        reject(err)
      },
    })
  })
}

/**
 * 高德地图 IP 定位
 * 文档地址: https://lbs.amap.com/api/webservice/guide/api/ipconfig
 */
export const ipToAddress = (ip?: string) => {
  return new Promise<Geometry>((resolve, reject) => {
    uni.request({
      url: `https://restapi.amap.com/v3/ip?key=${useAmapKeyStore().getAmapWebServiceKey}${ip ? `&ip=${ip}` : ''}`,
      success: (res: any) => {
        const result = res.data
        if (result.status === '1' && result.infocode === '10000') {
          // 左下坐标
          const locationLeftBottom: string[] = result.rectangle?.split(';')?.[0]?.split(',') || []
          // 右上坐标
          const locationRightTop: string[] = result.rectangle?.split(';')?.[1]?.split(',') || []
          let locationCenter = [] as unknown as [number, number]
          if (locationLeftBottom.length && locationRightTop.length) {
            // 保留八位小数
            locationCenter = [
              Number(((Number(locationLeftBottom[0]) + Number(locationRightTop[0])) / 2).toFixed(8)),
              Number(((Number(locationLeftBottom[1]) + Number(locationRightTop[1])) / 2).toFixed(8)),
            ]
          }
          console.log('高德ip获取位置信息成功,城市中心坐标:', locationCenter)
          resolve({
            type: GeometryType.Point,
            // 坐标只能定位到城市,所以选取城市中心点
            coordinates: locationCenter,
          })
        } else {
          console.log('高德ip获取位置信息失败', res)
          reject(res)
        }
      },
      fail: (err) => {
        console.log('高德ip获取位置信息请求失败', err)
        useLocationStore().SET_ADDRESS('获取地址失败，点击手动设置地址')
        reject(err)
      },
    })
  })
}

/**
 * 获取当前定位
 */
export const getLocation = () => {
  return new Promise<{ longitude: number; latitude: number; address?: string }>((resolve, reject) => {
    if (window?.navigator?.geolocation) {
      window.navigator.geolocation.getCurrentPosition(
        (position) => {
          console.log('浏览器高精度定位成功:', position.coords)
          resolve({
            latitude: position.coords.latitude,
            longitude: position.coords.longitude,
          })
        },
        (error) => {
          console.log('浏览器获取定位失败,尝试使用ip定位', error)
          // 尝试使用高德地图ip定位
          ipToAddress()
            .then((res) => {
              resolve({
                latitude: res.coordinates[1],
                longitude: res.coordinates[0],
              })
            })
            .catch((err) => {
              console.log('ip定位失败,彻底定位失败', err)
              reject(err)
            })
        },
        {
          enableHighAccuracy: true, //是否要求高精度的地理位置信息
          timeout: 3001, //对地理位置信息的获取操作做超时限制，如果再该事件内未获取到地理位置信息，将返回错误
        },
      )
    } else {
      // #ifdef MP-WEIXIN
      // 微信小程序获取位置信息
      uni.getLocation({
        type: 'gcj02',
        success: (lb) => {
          console.log('小程序获取定位成功', lb)
          resolve({
            latitude: lb.latitude,
            longitude: lb.longitude,
          })
        },
        fail: (error) => {
          console.log('小程序获取定位失败,尝试使用ip定位', error)
          // 尝试使用高德地图ip定位
          ipToAddress()
            .then((res) => {
              resolve({
                latitude: res.coordinates[1],
                longitude: res.coordinates[0],
              })
            })
            .catch((err) => {
              console.log('ip定位失败,彻底定位失败', err)
              reject(err)
            })
        },
      })
      // #endif
      // #ifndef MP-WEIXIN
      // 非小程序环境 直接尝试使用高德地图ip定位
      ipToAddress()
        .then((res) => {
          resolve({
            latitude: res.coordinates[1],
            longitude: res.coordinates[0],
          })
        })
        .catch((err) => {
          console.log('ip定位失败,彻底定位失败', err)
          reject(err)
        })
      // #endif
    }
  })
}
